#include <klib.h>
#include <klib-macros.h>
#include <stdint.h>

#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)

size_t strlen(const char *s) {
  size_t count = 0; 
  while (*s != '\0') {
    count++;
    s++;
  }
  return count;
}

char *strcpy(char *dst, const char *src) {
  char *p = dst;
  while (*src != '\0') {
    *p = *src;
    p++;
    src++;
  }
  *p = '\0';
  return dst;
}

char *strncpy(char *dst, const char *src, size_t n) {
  bool end = false;
  char* p = dst;
  for(; n > 0; n--) {
    if(*src == '\0') {
      end = true;
    }
    *p = end? '\0' : *src;
    p++;
    src++;
  }
  return dst;
}

char *strcat(char *dst, const char *src) {
  char* p = dst;
  while(*p != '\0') p++;
  strcpy(p, src);
  return dst;
}

int strcmp(const char *s1, const char *s2) {
  while (*s1 != '\0' || *s2 != '\0') {
    if(*s1 != *s2)
      return *s1 - *s2;
    s1++;
    s2++;
  }
  return 0; 
}

int strncmp(const char *s1, const char *s2, size_t n) {
  for(; n > 0; n--) {
    if(*s1 != *s2)
      return *s1 - *s2;
    if(*s1 == '\0')
      return 0;
    s1++;
    s2++;
  }
  return 0;
}

void *memset(void *s, int c, size_t n) {
  unsigned char fill = (unsigned char) c;
  unsigned char *p = (unsigned char *) s;
  for(; n > 0; n--) {
    *p = fill;
    p++;
  }
  return s;
}

void *memmove(void *dst, const void *src, size_t n) {
  unsigned char* p = (unsigned char*) src;
  unsigned char* d = (unsigned char*) dst;
  if (d < p) {
    while (n--) {
      *d = *p;
      d++;
      p++;
    }
  }
  else {
    while (n--) {
      *(d+n) = *(p+n);
    }
  }
  return dst;
}

void *memcpy(void *out, const void *in, size_t n) {
  return memmove(out, in, n);
}

int memcmp(const void *s1, const void *s2, size_t n) {
  unsigned char* a = (unsigned char*) s1;
  unsigned char* b = (unsigned char*) s2;
  while (n--) {
    if(*a != *b)
      return *a - *b;
    a++;
    b++;
  }
  return 0;
}

#endif
